import random, copy

class State(object):
    def __init__(self, Cards=[], Deck=sorted(range(4)*4), Pot=1):
        self.Cards = Cards
        self.Deck = Deck
        self.Pot = Pot
        
    def show(self):
        CardList = ["Jack", "Queen", "King", "Ace"]
        PCardsNames = []
        HCardsNames = []
        for i in range(0, len(self.Cards), 2):
            PCardsNames.append(CardList[i])
        for i in range(1, len(self.Cards), 2):
            HCardsNames.append(CardList[i])
        
        print "Player cards: ", PCardsNames
        print "House cards:  ", HCardsNames
        print "Pot size:     ", self.Pot

    def drawCard(self):
    # draw a random card and update the state
        DrawnCard = self.Deck[random.randint(0, len(self.Deck)-1)]
        self.Deck.remove(DrawnCard)
        self.Cards.append(DrawnCard)

    def winner(self):
    # return 1 = P wins, 0 = Draw, -1 = H wins    
        if len(self.Cards)==4:
            PPair = self.Cards[0]==self.Cards[2]
            HPair = HCards[1]==HCards[3]
            PHighcard = max(self.Cards[0],self.Cards[2])
            HHighcard = max(self.Cards[1],self.Cards[3])
            PKicker = min(self.Cards[0],self.Cards[2])
            HKicker = min(self.Cards[1],self.Cards[3])

            if PPair and not HPair:     return 1
            elif HPair and not PPair:   return -1
            elif PHighcard > HHighcard: return 1
            elif PHighcard < HHighcard: return -1
            elif PKicker > HKicker:     return 1
            elif PKicker < HKicker:     return -1
            else:                       return 0
            
        else:
            raise Exception, "Not enough cards to determine winner"

    def transitionModel(self, Bet):
        PossibleStates = []
        for Card in range(4):
            P = self.Deck.count(Card)/float(len(self.Deck))
            NewState = State(Cards=copy.copy(self.Cards), Deck=copy.copy(self.Deck), Pot=copy.copy(self.Pot))
            NewState.Deck.remove(Card)
            NewState.Cards.append(Card)
            NewState.Pot += Bet
            PossibleStates.append( (NewState, P) )
        return PossibleStates


def decideBet(PCard, HCard, Pot, Deck):
    #random policy
    Bet = random.randint(0,1)
    print "Player bets %d" %Bet
    return Bet

def winMessage(Winner, Pot):
    if Winner == 1:
        print "Congratulations, you have won %d dollar!" %Pot
    elif Winner == 0:
        print "This game ends in a draw"
    elif Winner == -1:
        print "House wins your %d dollar!" %Pot
    

def playRound( State ):
    (Cards, Deck, Pot) = State
    print "===================================================="
    try:
        Winner = winner(Cards)
        winMessage(Winner, Pot)

    except: 
        (DrawnCard, Deck) = drawCard(Deck)
        Cards.append(DrawnCard)

        printStatus(PCards, HCards)
        
        Bet = decideBet(PCards, HCards, Pot, Deck)
        Pot += Bet

        NewState = x
        playRound( NewState )
    
#playRound([J,K],[K,K], 1)
#def playerChances( PCards, HCards ):

def newGame():
    print "Let's play poker!\n"
    
    printStatus([], [])
    print "Player bets 1 to start the game"
    Deck = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
    Pot = 1
    playRound([], [], 1, Deck)

#newGame()
#print winner( [J,K], [K, K] )
        
from itertools import izip
argmax = lambda array: max(izip(array, xrange(len(array))))[1]


def vpolicy():
    Theta = 0.005
    Gamma = 0.9
    Delta = 0

    V = [0] * len(S) # or: [0 for s in S]
    while Delta < Theta:
        for s in xrange(len(S)):
            v = V[s]

            templist = [0] * len(A) # initialize temporary list of actions with zeroes
            for a in xrange(len(A)):
                for PState, PPoss in transitionModel(S[s], A[a]):
                    templist[a] = templist[a]+PPoss*(returnValue(PState)+gamma*vpolicy()))

            V[s] = max(templist)
            Delta = max(Delta,abs(v-V[s]))

    #return V
    # Instead of returning V, we simulate an argmax over all actions
    # to get the right action..
    x = 0
    arg = 0
    for a in xrange(len(A)):
        if templist[a]>x:
            x = templist[a]
            arg = a

    return arg
    # this outputs an action, rather than a policy - is this correct?
